package com.rfid.project.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;

import biz.util.*;

import com.rfid.project.model.*;
import com.rfid.project.dao.*;
import com.rfid.project.exception.CannotDelException;
import com.mysema.query.BooleanBuilder;

import java.util.Date;
import java.util.List;

@Service
@Transactional
public class ProjectService{

	@Autowired
	private ProjectDao projectDao;
	
	private QProject $ = QProject.project;

	@Autowired
	private ProjectStakeholderDao projectStakeholderDao;
	
	private QProjectStakeholder $_projectStatkeholder = QProjectStakeholder.projectStakeholder;

	@Autowired
	private ProjectMilestoneDao projectMilestoneDao;
	
	private QProjectMilestone $_2 = QProjectMilestone.projectMilestone;

	@Autowired
	private ProjectProductDao projectProductDao;
	
	private QProjectProduct $_3 = QProjectProduct.projectProduct;

	@Autowired
	private ProjectDeliveryDao projectDeliveryDao;

	private QProjectDelivery $_4 = QProjectDelivery.projectDelivery;

	@Autowired
	private ProjectMemberDao projectMemberDao;
	
	private QProjectMember $_5 = QProjectMember.projectMember;

	@Autowired
	private ProjectReportDao projectReportDao;
	
	private QProjectReport $_6 = QProjectReport.projectReport;
	
	@Autowired
	public void setProjectReportDao(ProjectReportDao projectReportDao) {
		this.projectReportDao = projectReportDao;
	}
	
	@Autowired
	public void setProjectMemberDao(ProjectMemberDao projectMemberDao) {
		this.projectMemberDao = projectMemberDao;
	}

	@Autowired
	public void setProjectDeliveryDao(ProjectDeliveryDao projectDeliveryDao) {
		this.projectDeliveryDao = projectDeliveryDao;
	}
	
	@Autowired
	public void setProjectProductDao(ProjectProductDao projectProductDao) {
		this.projectProductDao = projectProductDao;
	}
	
	@Autowired
	public void setProjectMilestoneDao(ProjectMilestoneDao projectMilestoneDao) {
		this.projectMilestoneDao = projectMilestoneDao;
	}
	
	@Autowired
	public void setProjectDao(ProjectDao projectDao) {
		this.projectDao = projectDao;
	}
	
	@Autowired
	public void setProjectStakeholderDao(ProjectStakeholderDao projectStakeholderDao) {
		this.projectStakeholderDao = projectStakeholderDao;
	}
	
	public List<Project> findAll(){
		return ListUtil.toList(projectDao.findAll());
	}
	
	public Project findOne(Long id){
		return this.projectDao.findOne(id);
	}
	
	public List<Project> findAll(
		String projectCode,
		String name,
		Date createDateBegin,
		Date createDateEnd,
		Date startDateBegin,
		Date startDateEnd,
		Date firstPlanFinishDateBegin,
		Date firstPlanFinishDateEnd,
		Date planFinishDateBegin,
		Date planFinishDateEnd,
		Date actualFinishDateBegin,
		Date actualFinishDateEnd,
		String projectDescription,
		Long departmentId,
		String projectPlanNo,
		String projectBatchNo,
		Long projectTypeId,
		Long projectSourceId,
		Long customerId,
		Long projectReportFrequencyId,
		String orderByAttribute	){
		BooleanBuilder condition = new BooleanBuilder();
		
		if(StringUtil.isNotEmpty(projectCode)){
			condition.and($.projectCode.contains(projectCode));
		}
		
		if(StringUtil.isNotEmpty(name)){
			condition.and($.name.contains(name));
		}
		
		if(createDateBegin != null){
			condition.and($.createDate.after(createDateBegin));
		}
		
		if(createDateEnd != null){
			condition.and($.createDate.before(createDateEnd));
		}
		
		if(startDateBegin != null){
			condition.and($.startDate.after(startDateBegin));
		}
		
		if(startDateEnd != null){
			condition.and($.startDate.before(startDateEnd));
		}
		
		if(firstPlanFinishDateBegin != null){
			condition.and($.firstPlanFinishDate.after(firstPlanFinishDateBegin));
		}
		
		if(firstPlanFinishDateEnd != null){
			condition.and($.firstPlanFinishDate.before(firstPlanFinishDateEnd));
		}
		
		if(planFinishDateBegin != null){
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}
		
		if(planFinishDateEnd != null){
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}
		
		
		if(actualFinishDateBegin != null){
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}
		
		if(actualFinishDateEnd != null){
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}
		
		if(StringUtil.isNotEmpty(projectDescription)){
			condition.and($.projectDescription.contains(projectDescription));
		}
		
		if(IdUtil.isNotEmpty(departmentId)){
			condition.and($.department.id.eq(departmentId));
		}
		
		if(StringUtil.isNotEmpty(projectPlanNo)){
			condition.and($.projectPlanNo.contains(projectPlanNo));
		}
		
		if(StringUtil.isNotEmpty(projectBatchNo)){
			condition.and($.projectBatchNo.contains(projectBatchNo));
		}
		
		if(IdUtil.isNotEmpty(projectTypeId)){
			condition.and($.projectType.id.eq(projectTypeId));
		}
		
		if(IdUtil.isNotEmpty(projectSourceId)){
			condition.and($.projectSource.id.eq(projectSourceId));
		}
		
		if(IdUtil.isNotEmpty(customerId)){
			condition.and($.customer.id.eq(customerId));
		}
		
		if(IdUtil.isNotEmpty(projectReportFrequencyId)){
			condition.and($.projectReportFrequency.id.eq(projectReportFrequencyId));
		}
		
		
		return ListUtil.toList(projectDao.findAll(condition));
	}		

	public Page<Project> findAll(
		String projectCode,
		String name,
		Date createDateBegin,
		Date createDateEnd,
		Date startDateBegin,
		Date startDateEnd,
		Date firstPlanFinishDateBegin,
		Date firstPlanFinishDateEnd,
		Date planFinishDateBegin,
		Date planFinishDateEnd,
		Date actualFinishDateBegin,
		Date actualFinishDateEnd,
		String projectDescription,
		Long departmentId,
		String projectPlanNo,
		String projectBatchNo,
		Long projectTypeId,
		Long projectSourceId,
		Long customerId,
		Long projectReportFrequencyId,
		int pageNumber, int pageSize,String sortAttribute,String orderDirection) {
		BooleanBuilder condition = new BooleanBuilder();

		if(StringUtil.isNotEmpty(projectCode)){
			condition.and($.projectCode.contains(projectCode));
		}
		if(StringUtil.isNotEmpty(name)){
			condition.and($.name.contains(name));
		}
		if(createDateBegin != null){
			condition.and($.createDate.after(createDateBegin));
		}
		
		if(createDateEnd != null){
			condition.and($.createDate.before(createDateEnd));
		}
		if(startDateBegin != null){
			condition.and($.startDate.after(startDateBegin));
		}
		
		if(startDateEnd != null){
			condition.and($.startDate.before(startDateEnd));
		}
		if(firstPlanFinishDateBegin != null){
			condition.and($.firstPlanFinishDate.after(firstPlanFinishDateBegin));
		}
		
		if(firstPlanFinishDateEnd != null){
			condition.and($.firstPlanFinishDate.before(firstPlanFinishDateEnd));
		}
		if(planFinishDateBegin != null){
			condition.and($.planFinishDate.after(planFinishDateBegin));
		}
		
		if(planFinishDateEnd != null){
			condition.and($.planFinishDate.before(planFinishDateEnd));
		}
		if(actualFinishDateBegin != null){
			condition.and($.actualFinishDate.after(actualFinishDateBegin));
		}
		
		if(actualFinishDateEnd != null){
			condition.and($.actualFinishDate.before(actualFinishDateEnd));
		}
		if(StringUtil.isNotEmpty(projectDescription)){
			condition.and($.projectDescription.contains(projectDescription));
		}
		if(IdUtil.isNotEmpty(departmentId)){
			condition.and($.department.id.eq(departmentId));
		}
		if(StringUtil.isNotEmpty(projectPlanNo)){
			condition.and($.projectPlanNo.contains(projectPlanNo));
		}
		if(StringUtil.isNotEmpty(projectBatchNo)){
			condition.and($.projectBatchNo.contains(projectBatchNo));
		}
		if(IdUtil.isNotEmpty(projectTypeId)){
			condition.and($.projectType.id.eq(projectTypeId));
		}
		if(IdUtil.isNotEmpty(projectSourceId)){
			condition.and($.projectSource.id.eq(projectSourceId));
		}
		if(IdUtil.isNotEmpty(customerId)){
			condition.and($.customer.id.eq(customerId));
		}
		if(IdUtil.isNotEmpty(projectReportFrequencyId)){
			condition.and($.projectReportFrequency.id.eq(projectReportFrequencyId));
		}

		Sort sortObject = null;
		if(StringUtil.isEmpty(sortAttribute)){
			sortObject = new Sort(Direction.DESC, "id");
		}else{
			sortObject = new Sort(Direction.fromStringOrNull(orderDirection),sortAttribute);
		}
		
		PageRequest pageRequest = new PageRequest(pageNumber - 1, pageSize, sortObject);
		return projectDao.findAll(condition, pageRequest);
	}
	
	public Project getProject(Long id){
		return projectDao.getOne(id);
	}
	
	public void deleteProject(Long id) throws CannotDelException{
		if (this.findCustomerByProject(id)) {
			throw new CannotDelException("项目已被项目干系人引用，无法删除！");
		} if(this.findProjectMilestoneChangeByProject(id)){
			throw new CannotDelException("项目已被项目节点引用，无法删除！");
		} if(findProjectProductByProject(id)){
			throw new CannotDelException("项目已被项目产品引用，无法删除！");
		} if(findProjectDeliveryByProject(id)){
			throw new CannotDelException("项目已被项目交付物引用，无法删除！");
		} if(findProjectMemberByProject(id)){
			throw new CannotDelException("项目已被项目成员引用，无法删除！");
		} if(findProjectReportByProject(id)){
			throw new CannotDelException("项目已被项目报告引用，无法删除！");
		} else {
			projectDao.delete(id);
		}
	}
	
	private boolean findCustomerByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_projectStatkeholder.project.id.eq(projectId));
		return this.projectStakeholderDao.count(condition) > 0;
	}
	
	private boolean findProjectMilestoneChangeByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_2.project.id.eq(projectId));
		return this.projectMilestoneDao.count(condition) > 0;
	}
	
	private boolean findProjectProductByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_3.project.id.eq(projectId));
		return this.projectProductDao.count(condition) > 0;
	}
	
	private boolean findProjectDeliveryByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_4.project.id.eq(projectId));
		return this.projectDeliveryDao.count(condition) > 0;
	}
	
	private boolean findProjectMemberByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_5.project.id.eq(projectId));
		return this.projectMemberDao.count(condition) > 0;
	}
	
	private boolean findProjectReportByProject(Long projectId){
		BooleanBuilder condition = new BooleanBuilder();
		condition.and($_6.project.id.eq(projectId));
		return this.projectReportDao.count(condition) > 0;
	}

	public void saveProject(Project project) {
		if (null == project.getCreateDate()) {
			project.setCreateDate(DateUtil.nowDate());;
		}
		if (null == project.getPlanFinishDateChangeCount()) {
			project.setPlanFinishDateChangeCount(0);
		}
		if(null == project.getPlanFinishDate()){
			project.setPlanFinishDate(project.getFirstPlanFinishDate());
		}
		if(IdUtil.isNotEmpty(project.getId())){
			Project sourceProject = this.projectDao.findOne(project.getId());
			sourceProject.setPlanFinishDateChangeCount(project.getPlanFinishDateChangeCount());
			sourceProject.setCreateDate(project.getCreateDate());
			sourceProject.setStatus(project.getStatus());
			sourceProject.setName(project.getName());
			sourceProject.setProjectCode(project.getProjectCode());
			sourceProject.setProjectSource(project.getProjectSource());
			sourceProject.setProjectReportFrequency(project.getProjectReportFrequency());
			sourceProject.setCustomer(project.getCustomer());
			sourceProject.setProjectType(project.getProjectType());
			sourceProject.setDepartment(project.getDepartment());
			sourceProject.setPlanFinishDate(project.getPlanFinishDate());
			sourceProject.setPlanConsumeWorkTime(project.getPlanConsumeWorkTime());
			sourceProject.setHardRate(project.getHardRate());
			sourceProject.setProjectPlanNo(project.getProjectPlanNo());
			sourceProject.setProjectBatchNo(project.getProjectBatchNo());
			sourceProject.setProjectDescription(project.getProjectDescription());
			
			projectDao.save(sourceProject);
		}else{
			projectDao.save(project);
		}
	}

	public void pullDownProject(Project project) {
		Project sourceProject = this.projectDao.findOne(project.getId());
		sourceProject.setStatus(project.getStatus());;
		sourceProject.setStartDate(DateUtil.nowDate());
		this.projectDao.save(sourceProject);
	}

}
		
